Eng_Lab 01 - introduction and Docker

Lab. 01 - Introduction and Docker

Docker logo

1. Introduction

What is this subject about?

Laboratory classes on Autonomous Mobile Robots aim to familiarize you with ways of dealing with challenges encountered while working with robots that, uncontrolled by humans, must perform tasks by moving in a variable space. The methods we will analyze can be used on a wide range of robots: from mobile warehouse platforms, through rescue drones, to autonomous cars.

What will the work look like?

During the classes, you will become acquainted with the instructions, perform the tasks presented in them, and ultimately, based on the knowledge acquired in this way, complete homework assignments (in the form of quizzes or programs to be written).

Periodically, “Problem-solving Laboratories” will take place where, after a common discussion at the beginning, you will be faced with an open problem, and the aim of the classes will be to develop a solution using your own knowledge, internet resources, and collaboration with the rest of the group. The homework after such classes will be to prepare a report on what was accomplished and present proposals for further steps. Satisfactory progress after these classes will enable you to earn additional points (more about grading).

Schedule

Grading

The assessment for laboratories will consist of two parts:

The total number of points obtained for both parts can be increased by additional points earned during the “problem-solving laboratories”.

FAQ

2. Docker

The aim of the further part of the classes is to learn the basics of using Docker and working with containers in Visual Studio Code.

Docker is described as a tool that allows putting a program and its dependencies (libraries, configuration files, local databases, etc.) in a lightweight, portable, virtual container that can be run on almost any server with a Linux-based kernel. Containers and their contents run independently of each other and are unaware of each other’s existence. However, they can communicate within strictly defined channels for information exchange. Thanks to running on a single shared operating system, software containerization is a much lighter (less resource-intensive) way of virtualization than full virtualization or paravirtualization using virtual operating systems.sourcesource

Work should begin with the installation of Docker.

Installation on Ubuntu 22.04

Note, in case of working on a computer in the laboratory, installation is not necessary. In that case, you can skip part of the instructions and go HERE. However, it would be good to go through these steps on your private computer because working with containers will be essential for homework assignments.

Preparing the Apt repository:

```bash sudo apt update sudo apt install ca-certificates curl gnupg curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg –dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg echo
“deb [arch="$(dpkg –print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu
\((. /etc/os-release && echo "\)VERSION_CODENAME“)” stable" |
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update

Installing Docker:

```bash<button class="flex ml-auto gizmo:ml-0 gap-2 items-center"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon-sm" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button>
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Verification of the installation:

```bash sudo docker run hello-world

### Managing Docker as a non-root user
Creating the `docker` group:

```bash<button class="flex ml-auto gizmo:ml-0 gap-2 items-center"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon-sm" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button>
sudo groupadd docker

Adding the current user to the docker group:

```bash sudo usermod -aG docker $USER

Update after group changes:

```bash<button class="flex ml-auto gizmo:ml-0 gap-2 items-center"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon-sm" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button>
newgrp docker

Verification of the configuration without sudo:

```bash docker run hello-world

### GUI applications
During classes, it will be necessary to run graphical applications, e.g., to preview camera images or display sensor readings. Therefore, **if someone has an Nvidia GPU card**, it is necessary to install the `NVIDIA Container Toolkit` package according to the [**instructions**](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#installation). It is also necessary to install Nvidia drivers to version >= 418.81.07 (this can be done using the `Software &amp; Updates` application -> `Additional Drivers` and selecting the appropriate driver).

If the computer is equipped with an Nvidia card and the drivers have been correctly installed, after running the command

```bash<button class="flex ml-auto gizmo:ml-0 gap-2 items-center"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon-sm" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button>
nvidia-smi

you should receive a response resembling this: Terminal with nvidia-smi

Here, you can see the driver version (535.86.05), the name of the graphics card (NVIDIA GeForce RTX 3080 Ti), and the current load (3%).

NVIDIA Container Toolkit Installation

Apt repository configuration:

```bash curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg –dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list |
sed ‘s#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g’ |
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
&&
sudo apt-get update

Installation of the package:

```bash<button class="flex ml-auto gizmo:ml-0 gap-2 items-center"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon-sm" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button>
sudo apt-get install -y nvidia-container-toolkit

Docker configuration:

```bash sudo nvidia-ctk runtime configure –runtime=docker sudo systemctl restart docker

## Working with Docker
When using Docker, you constantly encounter two concepts: `image` and `container`. It is extremely important to distinguish between them.


- **image** - a blueprint of a given system. It is used only for reading. It contains code, libraries, tools, dependencies, and other necessary files for execution. It can be created from a container using the `docker commit` command.
- **container** - is created when an image is run. It is an isolated place where an application can run without affecting the rest of the system. Once a container is stopped, it will not start automatically. After stopping the container, the changes made in it are saved.

### Docker vs. a virtual machine
Please find information online about how Docker differs from a virtual machine, its advantages, and disadvantages.

### Downloading an image and creating a container
Working with Docker should begin by downloading the *ubuntu* image:

```bash<button class="flex ml-auto gizmo:ml-0 gap-2 items-center"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon-sm" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button>
docker pull ubuntu

Then, it’s possible to create a container:

```bash docker run ubuntu:latest

By creating a container in this way, seemingly nothing happens. It is neither launched nor shown in the terminal. To immediately run the container after creating it and connect to it, the command should be invoked as follows:

```bash<button class="flex ml-auto gizmo:ml-0 gap-2 items-center"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon-sm" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button>
docker run -it ubuntu:latest bash

This way, the terminal immediately connects to the container, enabling further work.

You can exit the container with the command exit or using the key combination ctrl+d. After exiting, the container will be stopped, but its current state is saved.

A list of all created containers can be displayed using the command:

```bash docker container ls -a

where omitting `-a` will display only the running containers.

### Removing unnecessary containers
Please display the list of all containers and remove those created earlier during the classes using the command:

```bash<button class="flex ml-auto gizmo:ml-0 gap-2 items-center"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon-sm" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button>
docker container rm ...

where in place of ..., you should put the names of the containers to be deleted (it’s possible to provide several separated by space).

Using scripts to create containers

Preparing a container can be time-consuming, and essential arguments can easily be omitted, so it’s good practice to prepare bash files (.sh) that create containers.

Depending on hardware capabilities, using scripts for those without a GPU and with an NVIDIA GPU, you should create a container with the command:

```bash bash run_cpu.sh

or

```bash<button class="flex ml-auto gizmo:ml-0 gap-2 items-center"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon-sm" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button>
bash run_gpu_nvidia.sh

After running the scripts, the terminal should be connected to a container named ARM_01.

NOTE! The scripts automatically remove the ARM_01 container if it already exists on the computer.

Basic operations in Docker

A stopped container can be started with the command

```bash docker start ARM_01

You can connect to the container from multiple terminals with the command

```bash<button class="flex ml-auto gizmo:ml-0 gap-2 items-center"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon-sm" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button>
docker exec -it ARM_01 bash

You can stop the container with the command

```bash docker stop ARM_01

An <u>image</u> can be removed with the command:

```bash<button class="flex ml-auto gizmo:ml-0 gap-2 items-center"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon-sm" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button>
docker image rm ubuntu

Autocompletion in Docker

Sometimes, autocompletion using the TAB key is not installed by default in the downloaded image. You can install the package using the command

```bash apt install bash-completion

As you can see, when using Docker, you don't need to use the `sudo` command. By default, you are logged into the container as `root`.

### Simultaneous handling of multiple terminals
In many practical robotics applications, it's necessary to use multiple terminals simultaneously. Of course, you can switch between multiple terminal instances, but it's more convenient to use alternatives such as:


- Running commands in separate tabs. A new tab can be created with `ctrl+shift+t`. To switch tabs, you can use `alt+X`, where X is the terminal number, or `ctrl+PageUp/PageDown`.
- Using the [Terminator terminal](https://www.geeksforgeeks.org/terminator-a-linux-terminal-emulator/).
- Using the [tmux terminal](https://linuxhint.com/install-tmux-ubuntu/).

## Self-Study Tasks

- Create a container *ARM_01* using the [prepared scripts](#using-scripts-to-create-containers).
- Stop and start the container and connect multiple terminals to it.
- Install the `gedit` package in the container:

```bash<button class="flex ml-auto gizmo:ml-0 gap-2 items-center"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon-sm" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button>
apt update
apt install gedit

Addition: Docker in VS Code

Working with Docker can be somewhat cumbersome due to the constant need to navigate in the terminal. However, using Visual Studio Code, you can connect to a container and work on its files as if they were on the host.

VS Code Installation and Extensions

On computers in the laboratory, everything should already be installed.

All steps should be performed without using Docker.

From the VS Code page, download the .deb file and install it using the command

```bash sudo apt install ./.deb

VS Code can be launched from the application list or using the command

```bash<button class="flex ml-auto gizmo:ml-0 gap-2 items-center"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="icon-sm" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button>
code

From the extensions list on the left side (or ctrl+shift+x), search for Dev Containers(ms-vscode-remote.remote-containers) and install it.

Then, by clicking on the button in the lower-left corner (overlapping symbols “>” and “<”), choose “Attach to Running Container” and select the running container. If the container is not running, you need to start it as described above.

From this point on, you can write code, run it, and save it in the container using VS Code.


Author: Kamil Młodzikowski, Michał Nowicki